#include "udp_server.hpp"

//普通的数据拼接处理
std::string Handler(const std::string& str, const std::string clientip, const uint16_t clientport)
{
    std::cout << "[ip:" << clientip << "  port:" << clientport << "]-say# " << str << std::endl;
    return str;
}

//命令的安全检查
bool SafeCheck(const std::string& cmd)
{
    std::vector<std::string> key_word = {
        "rm",
        "mv",
        "cp",
        "kill",
        "unlink",
        "sudo",
        "uninstall",
        "yum",
        "top"
    };
    for(auto& word : key_word)
    {
        auto pos = cmd.find(word);
        if(pos != std::string::npos) return false;
    }
    return true;
}

//执行命令的方法
std::string ExcuteCommand(const std::string& cmd)
{
    std::cout << "client cmd:" << cmd << std::endl;

    if(!SafeCheck(cmd)) 
    {
        std::cout << "cmd is not safe" << std::endl;
        return "error";
    }

    //popen函数的作用：
    //1.创建子进程，并建立管道与子进程建立通信
    //2.会执行一个shell命令：由command提供
    //3.mode为r时，表示可以通过指向子进程标准输出的文件指针fp中读取数据
    //4.mode为w时，则fp是只想子进程标准输入的文件指针，可以通过该指针向子进程写数据
    //5.要用pclose手动的关闭管道，同时进行进程等待
    FILE* fp = popen(cmd.c_str(), "r");
    if(fp == nullptr)
    {
        perror("popen fail");
        return "error";
    }
    
    std::string result;
    char buffer[4096];
    while(true)
    {
        char* ok = fgets(buffer, 4096, fp);
        if(ok == nullptr) break;
        result += buffer;
    }
    pclose(fp);
    return result;
}

int main()
{
    UdpServer ser;
    ser.Init();
    ser.Run(Handler);
    return 0;
}